import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
 
/**
 * Gestisce l'interazione tra utente e grafo tramite 
 * shortcut da tastiera e mouse.      
 *
 * @author Massimiliano Ferretti matricola 79769 
 */

public class GraphListener
    implements MouseListener,
               KeyListener, 
               MouseMotionListener
{
    private GraphPanel graph;
    private JList output;
    private DefaultListModel listModel;
    
    /**
     * Costruttore che inizializza il listener con il grafo 
     * e il textbox sul quale scrivere l'output
     * @param graph Grafo
     * @param output Textbox 
     * @param listModel Oggetto che contiene la lista delle stringhe 
     * visualizzate in output          
     * @see GraphPanel
     */
    public GraphListener(GraphPanel graph, JList output, DefaultListModel listModel)
    {
        this.graph = graph;
        this.output = output;
        this.listModel = listModel;
    }
    
    private void executeAlgorithm(Algorithm algorithm)
    {
        algorithm.initialize(graph.getGraph(), listModel);
        graph.repaint();                                        
        
        algorithm.execute();
        graph.repaint();
    }
    
    // KeyListener
    public void keyPressed(KeyEvent e)
    {
        int keyCode = e.getKeyCode();
        
        // System.out.println("KeyCode: " + keyCode);
        // listModel.addElement("KeyCode: " + keyCode);
        
        Graph g = graph.getGraph();
        
        if(keyCode == KeyEvent.VK_DELETE)
            g.removeSelected();
        if(keyCode == KeyEvent.VK_Q)
            g.increaseCurrentArcWeight();
        if(keyCode == KeyEvent.VK_A)
            g.decreaseCurrentArcWeight();
        if(keyCode == KeyEvent.VK_D)
            executeAlgorithm(new Dijkstra());
        if(keyCode == KeyEvent.VK_B)
            executeAlgorithm(new BellmanFord());
        if(keyCode == KeyEvent.VK_TAB)
        {
            g.toggleShowHelp();
            System.out.println("Cambiato lo stato di visualizzazione help");
        }
        if(keyCode == KeyEvent.VK_S && e.isControlDown())
        {
            JFileChooser fc = new JFileChooser();
            fc.setDialogTitle("Salva il Grafo");
            int res = fc.showSaveDialog(graph);
            if(res == JFileChooser.APPROVE_OPTION)
            {
                java.io.File file = fc.getSelectedFile();
                System.out.println("Salvataggio grafo in: " + file.getAbsolutePath());
                g.save(file);
            }
            
        }
        if(keyCode == KeyEvent.VK_O && e.isControlDown())
        {
            JFileChooser fc = new JFileChooser();
            fc.setDialogTitle("Carica un Grafo");
            int res = fc.showOpenDialog(graph);
            if(res == JFileChooser.APPROVE_OPTION)
            {
                java.io.File file = fc.getSelectedFile();
                System.out.println("Caricamento grafo da: " + file.getAbsolutePath());
                g = Graph.load(file);
                graph.setGraph(g);
            }
        }
        if(keyCode == KeyEvent.VK_N && e.isControlDown())
            g.reset();
        
        graph.repaint();
    }
    
    public void keyReleased(KeyEvent e)
    {
    }
    
    public void keyTyped(KeyEvent e)
    {
    }
    // End KeyListener
    
    // MouseListener
    public void mousePressed(MouseEvent e)
    {
        int button = e.getButton();
        Graph g = graph.getGraph();
        
        if(button == MouseEvent.BUTTON1)
            g.select(e.getPoint());
        
        if(button == MouseEvent.BUTTON3)
            g.addNode(e.getPoint());
        
        graph.repaint();
    }
    
    public void mouseReleased(MouseEvent e)
    {
        graph.getGraph().endArcCreation(e.getPoint());
        graph.repaint();
    }
    
    public void mouseEntered(MouseEvent e)
    {
        graph.getGraph().setMousePos(e.getPoint());
        graph.repaint();
    }
    
    public void mouseExited(MouseEvent e)
    {
    }
    
    public void mouseClicked(MouseEvent e)
    {
    }
    // End MouseListener
    
    // MouseMotionListener
    public void mouseMoved(MouseEvent e)
    {
        Graph g = graph.getGraph();
        
        g.preSelect(e.getPoint());
        g.setMousePos(e.getPoint());
        
        graph.repaint();
    }
    
    public void mouseDragged(MouseEvent e)
    {
        boolean isLmb = (e.getModifiersEx() & MouseEvent.BUTTON1_DOWN_MASK) == MouseEvent.BUTTON1_DOWN_MASK;
        // System.out.println("Mouse " + button + " dragged: (" + mousePos.x + ";" + mousePos.y + ") -> (" + e.getX() + ";" + e.getY() + ")");
        Graph g = graph.getGraph();
        
        if(!e.isShiftDown() && isLmb)
            g.update(e.getPoint());
        
        if(e.isShiftDown() && isLmb)
            g.beginArcCreation(e.getPoint());
        
        g.preSelect(e.getPoint());
        g.updateArcCreation(e.getPoint());
        
        graph.repaint();
    }
    // End MouseMotionListener
}